<?php
require('autoload.php');
require_once('vendor/autoload.php');
include('log4php/Logger.php');
require('utils/ConvertType.php');
/**
 * Class Wxpusher
 *
 * @author freephp
 *
 * 参考：https://github.com/wxpusher/wxpusher-sdk-php/blob/master/wxpusher.class.php
 */
class WxPusher
{

    protected $appToken;

    protected $sendMsgUrl;

    protected $checkSendStatusUrl;

    protected $createQrCodeUrl;

    protected $searchFollowerUrl;

    protected $removeUserUrl;

    protected $rejectUserUrl;

    protected $logger;

    protected $curl;


    public function __construct()
    {
        // 从.env文件读取配置
        $dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
        $myEnv = $dotenv->load();

        // 初始化配置
        $this->appToken = $myEnv['appToken'];
        $this->sendMsgUrl = $myEnv['sendMsgUrl'];
        $this->checkSendStatusUrl = $myEnv['checkSendStatusUrl'];
        $this->createQrCodeUrl = $myEnv['createQrCodeUrl'];
        $this->searchFollowerUrl = $myEnv['searchFollowerUrl'];
        $this->removeUserUrl = $myEnv['removeUserUrl'];
        $this->rejectUserUrl = $myEnv['rejectUserUrl'];
        // 初始化log对象
//        Logger::configure('config/log.properties');
//        $log = Logger::getLogger("wx");
        Logger::configure('config.xml');

// Fetch a logger, it will inherit settings from the root logger
        $this->logger = Logger::getLogger('myLogger');
        $this->curl = new \Curl\SimpleCurl();


//        $log->warn("My fourth message.");   // Logged because WARN >= WARN
//        $log->error("My fifth message.");   // Logged because ERROR >= WARN
//        $log->fatal("My sixth message.");   // Logged because FATAL >= WARN


    }

    /**
     * POST方式请求发送消息接口
     *
     * @param $title 标题 对应参数中的summary
     * @param $content 内容 对应参数中的content
     *
     * {
     * "appToken":"AT_xxx",
     * "content":"Wxpusher祝你中秋节快乐!",
     * "summary":"消息摘要",//消息摘要，显示在微信聊天页面或者模版消息卡片上，限制长度100，可以不传，不传默认截取content前面的内容。
     * "contentType":1,//内容类型 1表示文字  2表示html(只发送body标签内部的数据即可，不包括body标签) 3表示markdown
     * "topicIds":[ //发送目标的topicId，是一个数组！！！，也就是群发，使用uids单发的时候， 可以不传。
     * 123
     * ],
     * "uids":[//发送目标的UID，是一个数组。注意uids和topicIds可以同时填写，也可以只填写一个。
     * "UID_xxxx"
     * ],
     * "url":"http://wxpusher.zjiecode.com" //原文链接，可选参数
     * }
     * @param  $targetTopicIds
     * @param  $targetUids
     * @param int $contentType
     */
    public function sendMsg($title, $content, $targetTopicIds, $targetUids = [], $contentType = 1, $url = "")
    {
        $postData = $this->initParam($title, $content, $targetTopicIds, $targetUids, $contentType, $url, true);


        $response = $this->curl->post($this->sendMsgUrl, $postData, true);


        return $this->__getResultAsArray($response);


//        if ($responseArray->code != 1000 || $responseArray->data[0]->code != 1000) {
//
//            echo date("Y-m-d H:i:s", time()) . "  " . $response;
//            $this->logger->error(date("Y-m-d H:i:s", time()) . "  " . $response);
//        }
//
//        return $responseArray->data[0]->messageId;
    }

    /**
     * GET方式请求发送消息接口，方便调用
     *
     * @param $title
     * @param $content
     * @param $targetTopicIds
     * @param array $targetUids
     * @param int $contentType
     * @param string $url
     * @return mixed
     * @throws ErrorException
     */
    public function sendMsgSimple($title, $content, $targetTopicIds, $targetUids = [], $contentType = 1, $url = "")
    {
        // http://wxpusher.zjiecode.com/api/send/message/?appToken=AT_qHT0cTQfLwYOlBV9cJj9zDSyEmspsmyM&content=123&uid=c1BcpqxEbD8irqlGUh9BhOqR2BvH8yWZ&url=http%3a%2f%2fwxpusher.zjiecode.com
        // content和url需要进行urlencode处理
        if ($contentType != 1) {
            $this->logger->warn("contentType不正确，必须是1！");
            die();
        }
        $getParams = $this->initParam($title, $content, $targetTopicIds, $targetUids, $contentType, $url);

        $getParams['content'] = urlencode($getParams['content']);
        $getParams['summary'] = urlencode($getParams['summary']);
        $getParams['url'] = urlencode($getParams['url']);


        $response = $this->curl->get($this->sendMsgUrl . http_build_query($getParams));

        return $this->__getResultAsArray($response);


//        if ($responseArray->code != 1000 || $responseArray->data[0]->code != 1000) {
//
//            echo date("Y-m-d H:i:s", time()) . "  " . $response;
//            $this->logger->error(date("Y-m-d H:i:s", time()) . "  " . $response);
//        }
//
//        return $responseArray->data[0]->messageId;

    }

    /**
     * 可以根据message ID查询发送的消息状态
     *
     * 消息发送给Wxpusher，Wxpusher会缓存下来，后台异步推送给微信再分发给用户，当消息数量庞大的时候，可能会有延迟，你可以根据发送消息返回的messageId，查询消息的发送状态

    请求方式：GET

    说明：查询消息状态，消息缓存有时效性，目前设置缓存时间为7天，7天后查询消息，可能会返回消息不存在

    请求地址：http://wxpusher.zjiecode.com/api/send/query/{messageId}
     */
    public function checkSendStatus(string $messageId): array
    {
//        echo $this->checkSendStatusUrl  . $messageId;die();

        $response = $this->curl->get($this->checkSendStatusUrl  . '/' . $messageId);

        return $this->__getResultAsArray($response);
    }

    /**
     * 创建参数二维码
     * @param string $extraInfo 二维码携带参数，必填，最长64位
     * @param int $expireTime   二维码有效期，可选参数，默认30分钟，最长30天，单位是秒
     * @return array
     * @throws ErrorException
     */
    public function createQrcode(string $extraInfo, int $expireTime = 1800): array
    {
        $postData = $this->__makeQrcodePostData($extraInfo, $expireTime);


        $response = $this->curl->post($this->createQrCodeUrl, json_encode($postData), true);

        return $this->__getResultAsArray($response);
    }


    /**
     * GET请求
     * appToken 应用密钥标志
    page 请求数据的页码
    pageSize 分页大小，不能超过100
    uid 用户的uid，可选，如果不传就是查询所有用户，传uid就是查某个用户的信息。
    isBlock 查询拉黑用户，可选，不传查询所有用户，true查询拉黑用户，false查询没有拉黑的用户
    type 关注的类型，可选，不传查询所有用户，0是应用，1是主题。 返回数据：

     */
    public function getFollower(int $page = 0, int $pageSize = 50, string $uid = null, $isBlock = null, $type = null)
    {
        $query = [
            'appToken' => $this->appToken,
            'page' => $page,
            'pageSize' => $pageSize
//            'uid' => $uid,
//            'isBlock' => $isBlock,
//            'type' => $type
        ];
        if ($pageSize > 100) {
            $this->logger->warn("分页大小（pageSize）不能超过100！");
            die();
        }

        if (isset($isBlock) && !is_bool($isBlock)) {
            $this->logger->warn("如果传递了isBlock，它的值只能是true或者false");
            die();
        }
        if (isset($type) && !in_array($type, [0, 1])) {
            $this->logger->warn("type可以不传，但是如果传递了，必须是0或者1");
            die();
        }

        if ($isBlock != null) {
            $query['isBlock'] = $isBlock;
        }
        if ($uid != null) {
            $query['uid'] = $uid;
        }

        if ($type != null) {
            $query['type'] = $type;
        }

        $response = $this->curl->get($this->searchFollowerUrl . '?' . http_build_query($query));

        return $this->__getResultAsArray($response);
    }

    /**
     * 删除用户
    你可以通过本接口，删除用户对应用，主题的关注。

    请求方式：DELETE

    说明：你可以删除用户对应用、主题的关注，删除以后，用户可以重新关注，如想让用户再次关注，可以调用拉黑接口，对用户拉黑。

    请求地址：http://wxpusher.zjiecode.com/api/fun/remove

    请求参数：

    appToken 应用密钥标志
    id 用户id，通过用户查询接口可以获取
    返回数据：

    {
    "code": 1000,
    "msg": "处理成功",
    "data": "删除成功",
    "success": true
    }
     */
    public function removeUser(string $uid): array
    {
        $deleteParams = [
            'appToken' => $this->appToken,
            'uid' => $uid
        ];

        $response = $this->curl->delete($this->removeUserUrl, $deleteParams);

        return $this->__getResultAsArray($response);
    }

    /**
     * 你可以通过本接口，可以拉黑用户

    请求方式：PUT

    说明：拉黑以后不能再发送消息，用户也不能再次关注，除非你取消对他的拉黑。调用拉黑接口，不用再调用删除接口。

    请求地址：http://wxpusher.zjiecode.com/api/fun/reject

    请求参数：

    appToken 应用密钥标志
    id 用户id，通过用户查询接口可以获取
    reject 是否拉黑，true表示拉黑，false表示取消拉黑
    返回数据：

    {
    "code": 1000,
    "msg": "处理成功",
    "data": "删除成功",
    "success": true
    }
     */
    public function rejectkUser($uid = '', $reject = true)
    {
        $rejectData = [
            'id' => $uid,
            'reject' => $reject
        ];

        $response = $this->curl->put($this->rejectUserUrl, json_encode($rejectData));

        return $this->__getResultAsArray($response);
    }

    /**
     * 组装创建参数二维码的post数据
     *
     * @param string $extraString 二维码携带的参数
     * @param int $validTime 二维码有效时间 单位秒
     * @return array post数据数组
     */
    private function __makeQrcodePostData(string $extraString, int $validTime = 1800):array {
        if ($extraString == '') {
            $this->logger->warn("二维码所带的参数是必填的");
            exit("extra should have value");
        } else if (strlen($extraString) > 64) {
            $this->logger->warn("二维码所带参数长度不能超过64位");
            exit("extra length limit");
        }
        if ($validTime > 30*3600*24) {
            $this->logger->warn("二维码有效期不能超过30天，单位秒！");
            exit("valid time can not be more then 30 days");
        }
        $postData = [
            'appToken' => $this->appToken,
            'extra' => $extraString,
            'validTime' => $validTime
        ];

        return $postData;
    }


    private function initParam($title, $content, $targetTopicIds, $targetUids = [], $contentType = 1, $url = "", $isPost= false) {
        if (!in_array($contentType, [1, 2, 3])) {
            $this->logger->warn("contentType不正确，必须是1，2，3中的一个！");
            exit("contentType error!");
        }
        $postData = [
            'appToken' => $this->appToken,
            'content' => $content,
            'summary' => $title,
            'contentType' => $contentType
        ];
        if (is_numeric($targetTopicIds)) {
            $postData['topicIds'] = [$targetTopicIds];

        } else if (is_array($targetTopicIds) && !empty($targetTopicIds)) {
            $postData['topicIds'] = $targetTopicIds;
        }

        if (is_numeric($targetUids)) {
            $postData['uids'] = [$targetUids];

        } else if (is_array($targetUids) && !empty($targetUids)) {
            $postData['uids'] = $targetUids;
        }

        $postData['url'] = $url;
        if ($isPost) {
            $postData = json_encode($postData);
        }

         return $postData;
    }


    private function __getResultAsArray($jsonObject) {
        $responseArray = (array)json_decode($jsonObject);

        return ConvertType::objectToArray($responseArray);
    }

}




